package platform;

import common.Constant;
import operator.Handler;
import pri.swg.Fader;
import resource.Resource;
import common.Singleton;
import view.Main;
import view.ViewControl;
import vo.Mean;

import javax.swing.*;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

/**
 * 意象展示标签（右面版）
 *
 * @author 柴家琪
 */
public class MeanLabel extends JLabel {
    private Handler handler;
    private ViewControl vc;
    private Main main;

    private static final long serialVersionUID = 1L;
    public static final int MainMeanTop = 1, ViceMeanTop = 2, Location = 3, defaultHeight = 22;
    private static final String labelSeparator = "︴";
    public ArrayList<MeanLabel> offsets;
    public MeanLabel relateTo;
    private MeanLabel thisone;
    public Mean sourceMean;
    boolean offsetsVisible = false;
    private boolean isOffset = true;
    boolean enable = true;// 后代可视、是否是后代
    public int type;
    public MeanPlatform group_plat;
    private Fader fader;
    private TinyButton tinyButton;// 小按钮
    private Font defaultFont = new Font(Constant.boldfaceName, Font.BOLD, 18);
    private boolean existHidden = false;
    private Color bg = Color.DARK_GRAY;


    /**
     * 获取指定意象的所有标签
     * TODO 在 Mean 中添加集合储存 Labels，使用个别更新取代全部重置
     */
    public static MeanLabel[] getAllLabel(Mean m, int id) {
        // 0 的位置是字段标签，1 的位置是位置标签
        MeanLabel[] all = new MeanLabel[2];
        int index = 1;
        if (m.getInner_id() == 0)
            all[0] = new MeanLabel(id + labelSeparator + m.getTextForShow(), MainMeanTop, m);
        else
            all[0] = new MeanLabel(m.getTextForShow(), ViceMeanTop, m);

        all[0].offsets = new ArrayList<>();
        // 添加地址标签
        all[index] = new MeanLabel(m.getDescription(), Location, m);
        all[0].offsets.add(all[index]);
        all[index].relateTo = all[0];
        all[0].isOffset = false;

        // 改变边框颜色
        boolean fulled = m.isFulled();
        all[0].setBorderColor(fulled);
        if (m.getInner_id() == 0)
            m.getLabel().setBorderColor(fulled);
        else if (!fulled)
            m.getMain().getLabel().setBorderColor(false);

        return all;
    }

    private MeanLabel() {
        handler = Singleton.handler();
        vc = Singleton.vc();
        main = Singleton.main();
    }

    private MeanLabel(String s, int type, Mean sourceMean) {
        this();

        thisone = this;
        this.type = type;
        this.sourceMean = sourceMean;
        setText(s);
        setOpaque(true);
        setFont(defaultFont);
        setVisible(false);
        setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
        // setBorderColor(new LineBorder(Color.RED,1));
        switch (type) {
            // 意象标签
            case MainMeanTop:
                this.bg = Color.ORANGE;
                setVisible(true);
            case ViceMeanTop:
                if (type == ViceMeanTop)
                    this.bg = Color.GREEN;
                setBackground(bg);
                sourceMean.setLabel(this);
                setHorizontalAlignment(JLabel.LEFT);
                setForeground(Color.BLACK);
                setPreferredSize(new Dimension(30 + s.length() * 14, defaultHeight));
                offsets = new ArrayList<>();
                //
                setToolTipText("图标展开，左键显示，右键更多操作");
                tinyButton = new TinyButton(this);
                add(tinyButton);
                break;
            // 位置
            case Location:
                setBorder(new MatteBorder(0, 0, 1, 1, Color.white));
                setToolTipText("位置（右键更多操作）");
                setBackground(Color.DARK_GRAY);
                setForeground(Color.white);
                setPreferredSize(new Dimension(10 + s.length() * 14, defaultHeight));
                setHorizontalAlignment(JLabel.CENTER);
        }
        if (type == MainMeanTop || type == ViceMeanTop) {
            fader = Fader.fade(this, Fader.FORE_GROUND, 100, Fader.RETURN, Color.WHITE);
        } else if (type == Location)
            fader = Fader.fade(this, Fader.BACK_GROUND, 100, Fader.RETURN, Color.LIGHT_GRAY);
        addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                if (enable)
                    fader.goOn();
            }

            public void mouseExited(MouseEvent e) {
                if (enable)
                    fader.goBack();
            }

            public void mouseReleased(MouseEvent e) {
                if (enable) {
                    // if(type!=Location)
                    switchSelectState();
                    if (e.getButton() == MouseEvent.BUTTON1) {
                        handler.recoveryTextColor();
                        showInText();
                        vc.info_refreshInfo(vc.pre);
                        handler.getText()
                                .setCaretPosition(main.presentPage < 1 ? sourceMean.getTop() : sourceMean.getPageFrom());

                        if (isOffset)
                            vc.showShower(relateTo.sourceMean);
                        else
                            vc.showShower(sourceMean);

                    }
                    if (e.getButton() == MouseEvent.BUTTON3) {
                        if (type == MainMeanTop || type == ViceMeanTop) {
                            vc.showMenus_MeanOperate();
                        } else if (type == Location) {
                            vc.showMenus_LocOperate();
                        }
                    }
                }
            }
        });
    }

    /**
     * 切换视图上的可视性，将自动显示或隐藏副意象的可视性（递归）
     */
    void switchVisible() {
        if (offsets != null) {
            handler.recoveryTextColor();// 每次点开或者合上 恢复
            // ArrayList<MeanLabel> hidden=new ArrayList<>();
            for (MeanLabel vice_label : offsets) {
                vice_label.setVisible(!offsetsVisible);// 使后代不可视
                // 可视
                if (!offsetsVisible) {
                    if (vice_label.suitableForShow())
                        vice_label.showInText();// 子代当前合理则显示
                    if (vice_label.sourceMean.isHidden())
                        handler.Offset++;
                }
                // 不可视 (虽然已经设置了不可视，但offsetsVisible还是true)
                else if (vice_label.offsets != null && vice_label.offsetsVisible) {
                    // after closed main mean,colse all vice mean
                    vice_label.switchVisible();
                    vice_label.tinyButton.switchIcon();
                }
            }
            if (handler.Offset != 0)
                existHidden = true;// 不等于0说明显示过隐含意象
            handler.Offset = 0;
            if (offsetsVisible && type != Location) {
                if (existHidden) {
                    handler.setPage(main.presentPage);// 直接使用设置页面的方法来恢复
                    // handler.explicitDisplay(); //此方法中已经包含了showInText,所以隐含意象会显示两根
                    existHidden = false; // 显式显示过之后为 未显示过
                }
                showInText();
            }
            offsetsVisible = !offsetsVisible;
            getGroup_plat().reSetVisible();
        }
    }

    void switchSelectState() {
        vc.callBackAll();
        if (vc.preSelected != null)
            vc.preSelected.getGroup_plat().beSelected(false);
        // vc.preSelected.setBorder(vc.preBorder);
        vc.preSelected = thisone;
        getGroup_plat().beSelected(true);
    }

    private void showInText() {
        {
            if (type == MainMeanTop || type == ViceMeanTop) {
                handler.showMean(sourceMean, thisone.getBackground());
            }
            else {
                handler.showMean(sourceMean, relateTo.getBackground());
            }
        }
    }

    public void reSetText(String text) {
        setText(text);
        reSetLength();
    }

    private void reSetLength() {
        setPreferredSize(new Dimension(10 + this.getText().length() * 14, 20));
    }

    public MeanPlatform getGroup_plat() {
        if (group_plat == null && type == Location)
            group_plat = relateTo.group_plat;
        return group_plat;
    }

    void setGroup_plat(MeanPlatform group_plat) {
        this.group_plat = group_plat;
    }

    public void setVisible(boolean visible) {
        super.setVisible(visible);// 只有主意象且“适合”显示，才在初始化时显示
        enable = suitableForShow();

        if (tinyButton != null)
            tinyButton.setEnabled(enable);
        setBackground(bg);
    }

    /**
     * @return 是否适合显示（只有在全文或对应段落时才合适）
     */
    private boolean suitableForShow() {
        return sourceMean.getSuitPage() == main.presentPage || main.presentPage == 0;
    }

    public void setBackground(Color background) {
        if (enable)
            super.setBackground(background);
        else
            super.setBackground(Color.LIGHT_GRAY);
    }

    /**
     * 改变此标签的边框颜色
     */
    public void setBorderColor(boolean attrsFulled) {
        setBorder(new MatteBorder(0, 0, 1, 0,
                attrsFulled ? Color.WHITE : new Color(255, 0, 0)));
    }
}

class TinyButton extends JPanel {
    private static final long serialVersionUID = 1L;
    private Resource resource = Singleton.resource();
    private ImageIcon open = resource.getIcon("narrow_right.png");
    private ImageIcon close = resource.getIcon("narrow_left.png");
    private MeanLabel m;
    private JLabel icon = new JLabel(open);

    TinyButton(MeanLabel m) {
        this.m = m;
        int height = MeanLabel.defaultHeight;
        int interval = (height - 16) / 2;
        setPreferredSize(new Dimension(20, height));
        setOpaque(false);
        setLayout(null);
        icon.setBounds(interval, interval, 16, 16);
        add(icon);
        addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                if (m.enable)
                    setCursor(new Cursor(Cursor.HAND_CURSOR));
            }

            public void mouseExited(MouseEvent e) {
                if (m.enable)
                    setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }

            public void mouseReleased(MouseEvent e) {
                if (m.enable) {
                    m.switchVisible();
                    m.switchSelectState();
                    switchIcon();
                }
            }
        });
    }

    void switchIcon() {
        if (m.offsetsVisible)
            icon.setIcon(close);
        else
            icon.setIcon(open);
    }

}